package com.zzb.framework.query;

import com.baomidou.mybatisplus.annotations.TableName;
import com.zzb.framework.common.BasePage;
import com.zzb.framework.common.PageSearchForm;
import com.zzb.framework.query.sqlbuilder.CountSqlBuilder;
import com.zzb.framework.query.sqlbuilder.OrderByBuilder;
import com.zzb.framework.query.sqlbuilder.PagionageSqlBuilder;
import com.zzb.framework.query.sqlbuilder.QueryMethodBuilder;
import com.zzb.framework.utils.ReflectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * genericQueryDAO 接口 支持Mysql Postgres 切换
 * Created by zhangzhenbin on 17-8-9.
 */
public interface GenericQueryDAO {
    Logger getLogger();
    PagionageSqlBuilder getPagionageSqlBuilder();
    JdbcTemplate getJdbcTemplate();

    default  <T> BasePage<T> queryPage(String querySql, Class<T> clazz, int page, int pageSize, Object... params) throws QueryException {
        try {
            String countSql = CountSqlBuilder.getCountSql(querySql);
            String limitSql = getPagionageSqlBuilder().build(page, pageSize);
            querySql = querySql + limitSql;
            long total = getJdbcTemplate().queryForObject(countSql, Long.class, params);
            List<T> list = getJdbcTemplate().query(querySql, new AnnotationColumnRowMapper<T>(clazz), params);
            return new BasePage<T>(list, page, pageSize, total);
        } catch (DataAccessException e) {
            throw new QueryException("DataAccessException", e);
        }
    }

    default  <S extends PageSearchForm, T> BasePage<T> queryPage(S searchForm, Class<T> clazz, String ... tableNames) {
        try {
            //构建预定义系统
            List<QueryMethodItem> methodItemList = QueryMethodBuilder.build(searchForm, clazz);
            String tableName;
            if(ArrayUtils.isEmpty(tableNames)){
                TableName table = clazz.getAnnotation(TableName.class);
                if(table  != null){
                    tableName  = table.value();
                } else {
                    tableName = clazz.getName();
                }
            } else {
                tableName = tableNames[0];
            }
            Field[] allDeclaredFields = ReflectionUtils.getAllDeclaredFields(clazz);

            //查询SQL初始化
            String querySql = "select t.* ";
            String countSql = " select count(1) ";

            //查询条件
            StringBuilder sqlCondition =
                    new StringBuilder(" from " + tableName + " t where 1= 1 ");
            List<Object> params = new ArrayList<>();
            QueryMethodBuilder.methodItemListBuilder(methodItemList, sqlCondition, params);

            //排序
            String orderBy;
            if (StringUtils.isNotBlank(searchForm.getOrderBy())) {
                orderBy = searchForm.getOrderBy();
                if (!orderBy.contains("order by"))
                    orderBy = " order by " + orderBy;
            } else {
                orderBy = OrderByBuilder.getOrderByFields(allDeclaredFields);
            }

            //分页
            String limitString = getPagionageSqlBuilder().build(searchForm.getPage(),searchForm.getPageSize());

            querySql = querySql + sqlCondition.toString() + orderBy + limitString;
            countSql += sqlCondition;
            List<T> list = getJdbcTemplate().query(querySql, new AnnotationColumnRowMapper<T>(clazz), params.toArray());
            Long count = getJdbcTemplate().queryForObject(countSql, Long.class, params.toArray());
            getLogger().info(querySql);

            return new BasePage<>(list, searchForm.getPage(), searchForm.getPageSize(), count);
        } catch (IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
            return null;
        }
    }
}
